home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
mac
/
source
/
music4c.sit
/
Music4C Folder
/
Sources Folder
/
ugenlib.c
< prev
next >
Wrap
Text File
|
1990-06-22
|
49KB
|
2,079 lines
/*
* ⌐ Graeme Gerrard 1990
* Faculty of Music, University of Melbourne
* Parkville Victoria 3052 Australia.
*
* ARPANET: grae@murdu.ucs.unimelb.edu.au
* telephone: (613) 344 4127, Fax: (613) 344 5346
*/
/* WARNING: Beware of (int) casts for truncation. Remember, THINK C ints
are only 16 bits!. This may cause trouble when truncating large numbers,
like sample numbers!
*/
#include "Music4C.h"
#include "orch.h"
#include <math.h>
#include <unix.h>
#include "Music4C_Prototype.h"
#include "ErrorAlert.h"
#include "SDtype.h"
extern int loc;
extern double *out;
extern int nchnls;
extern double *F[MAXFUNCS];
extern double srate;
extern OSErr theErr;
extern Str255 theMess1;
double add8vepc(p1, p2)
double p1, p2;
{
double c1, c2, temp, nclass;
int pos, oct1, oct2, octnxt;
/* adds together 2 8ve.pc pitches */
oct1 = (int)p1;
c1 = p1 - oct1;
oct2 = (int)p2;
if ( oct2 < 0 ) {
pos = -oct2;
c2 = p2 + (double)pos;
}
else
c2 = p2 - (double)oct2;
temp = (c1+c2) * 100.0; /* shift for roundoff/truncation */
octnxt = (int)(temp/12.0) + oct1 + oct2;
if ( temp < 0.0 ) {
octnxt -= 1;
nclass = (12.0 + (int)temp % 12) / 100.0;
}
else {
nclass = ((int)temp % 12) / 100.0;
}
return(octnxt+nclass);
}
void en3set( ta, ts, td, a )
double ta, ts, td, *a;
{
register n;
register double fac = 128.0 / srate;
register double st = 1.0 / srate;
register double t[3];
*t = ta;
*(t+1) = ts;
*(t+2) = td;
for ( n = 0; n < 3; n++ ) {
if ( *(t+n) <= st ) *(t+n) = st;
*(a+n) = fac / *(t+n);
}
*(a+3) = 1.0 - *(a);
} /* en3set */
double envel3(amp, fno, a)
double amp, *a;
int fno;
{
register k;
if ( *(a+3) < 128.0) {
*(a+3) += *(a);
if (*(a+3) > 128.0) *(a+3) = 128.0;
}
else if (*(a+3) < 256.0) {
*(a+3) += *(a+1);
if (*(a+3) > 256.0) *(a+3) = 256.0;
}
else if (*(a+3) < 384.0) {
*(a+3) += *(a+2);
if (*(a+3) > 384.0) *(a+3) = 384.0;
}
else
*(a+3) = 384.0;
k = (int)(*(a+3) + 0.5); /* round to add 1 for length in F[0] */
return(amp * *(F[fno] + k));
}
double envel3I(amp, fno, a)
double amp, *a;
int fno;
{
/* interpolating version of envel3 */
register k, l;
double diff;
if ( *(a+3) < 128.0) {
*(a+3) += *(a);
if (*(a+3) > 128.0) *(a+3) = 128.0;
}
else if (*(a+3) < 256.0) {
*(a+3) += *(a+1);
if (*(a+3) > 256.0) *(a+3) = 256.0;
}
else if (*(a+3) < 384.0) {
*(a+3) += *(a+2);
if (*(a+3) > 384.0) *(a+3) = 384.0;
}
else
*(a+3) = 384.0;
if ( *(a+3) >= 384 )
return(amp * *(F[fno] + 384));
else {
k = *(a+3);
l = k+1;
diff = *(a+3) - (int)*(a+3);
return(amp * (*(F[fno] + k) + ((*(F[fno]+l)-*(F[fno]+k)) * diff)) );
}
}
void adsrset( att, dec, sus, rel, a )
double att, dec, sus, rel, *a;
{
register n;
register double fac = 128.0 / srate;
register double st = 1.0 / srate;
register double t[4];
*t = att;
*(t+1) = dec;
*(t+2) = sus;
*(t+3) = rel;
for ( n = 0; n < 4; n++ ) {
if ( *(t+n) <= st ) *(t+n) = st;
*(a+n) = fac / *(t+n);
}
*(a+4) = 1.0 - *(a);
} /* adsrset */
double adsr(amp, fno, a)
double amp, *a;
int fno;
{
register k;
if ( *(a+4) < 128.0) {
*(a+4) += *(a);
if (*(a+4) > 128.0) *(a+4) = 128.0;
}
else if (*(a+4) < 256.0) {
*(a+4) += *(a+1);
if (*(a+4) > 256.0) *(a+4) = 256.0;
}
else if (*(a+4) < 384.0) {
*(a+4) += *(a+2);
if (*(a+4) > 384.0) *(a+4) = 384.0;
}
else if (*(a+4) < 512.0) {
*(a+4) += *(a+3);
if (*(a+4) > 512.0) *(a+4) = 512.0;
}
else
*(a+4) = 512.0;
k = (int)(*(a+4) + 0.5); /* round to add 1 for length in F[0] */
return(amp * *(F[fno] + k));
}
void blnset( bw, xinit, a )
double bw, xinit, *a;
{
void toneset();
/* bw = 10.0 usual */
toneset(bw, xinit, a);
toneset(bw, xinit, (a+3));
}
void cmbset( xloopt, xinit, a )
double xloopt, xinit, *a;
{
register n;
int le;
*(a) = 4.0 + (long)(xloopt * srate + 0.5);
*(a+1) = xloopt;
if ( xinit <= 0.0 ) {
le = *(a);
for ( n = 5; n < le; n++)
*(a+n) = 0.0;
*(a+2) = 0.0;
*(a+3) = 0.0;
*(a+4) = 4.0;
}
}
void slpset(a, b, dur)
double *a, *b, dur;
{
*b = ( *b - *a) * ( 1.0 / (dur * srate));
*a -= *b;
}
double slope(a, b)
double *a, *b;
{
*a += *b;
return( *a );
}
void toneset( hpoint, xinit, a )
double hpoint, xinit, *a;
{
register double twopi = 8.0 * atan(1.0);
register double b = 2.0 - cos(hpoint * twopi / srate);
*(a+1) = b - sqrt(b*b - 1.0);
*(a) = 1.0 - *(a+1);
if ( hpoint < 0.0 ) *(a+1) = -*(a+1);
if ( xinit <= 0.0) *(a+2) = 0.0;
}
double tone(x, a )
double x, *a;
{
*(a+2) = (*(a) * x) + (*(a+1) * *(a+2));
return(*(a+2));
}
void evpset(delay, rise, dur, decay, nf1, nf2, a )
double delay, rise, dur, decay, *a;
int nf1, nf2;
{
*(a) = period(rise);
/* old *(a+1) = (srate * delay * *(a));*/
*(a+1) = -(srate * delay * *(a));
*(a+2) = -(period(decay));
*(a+3) = (511.9999 + *(a+2)) - (srate * (dur-decay) * *(a+2));
*(a+4) = (*(F[nf1] + 512)) * (*(F[nf2] + 512));
}
double envlp(amp, nf1, nf2, a )
double amp, *a;
int nf1, nf2;
{
register double x;
x = oscil1(amp, *(a), nf1, (a+1));
return( oscil1(x, *(a+2), nf2, (a+3)) / *(a+4));
}
void expset(a, b, dur)
double *a, *b, dur;
{
*b = pow( *b / *a , 1.0 / (dur * srate));
*a /= *b;
}
double expon(a, b)
double *a, *b;
{
*a *= *b;
return( *a );
}
double formnt( rms, si, fno1, fno2, fno3, fno4, a)
double rms, si, *a;
int fno1, fno2, fno3, fno4;
{
register double coef, freq;
register i, j, k;
double x, ss, z, t;
/* a[0] = overall phase */
/* a[1] = previous sum of squares */
/* a[2] = rescaling divisor */
ss = 0.0;
if ( rms != 0.0 ) {
z = 0.0;
for ( i = 1; i <= 508; i += 3 ) {
freq = *(F[fno2]+i);
if ( freq == 0.0 )
break; /*goto L4;*/
j = (long)(freq * si * 2.0 + 1.5);
if ( j > 512)
break; /*goto L4;*/
coef = *(F[fno2]+i+1) * *(F[fno3]+j);
if ( fno4 <= 0)
x = coef;
else
x = coef / *(F[fno4]+j);
ss += (x * x );
k = ((long)((freq * *a) + *(F[fno2]+i+2)) % 512) + 1.0;
z += (coef * *(F[fno1]+k));
}
}
L4:
*a += si;
while ( *a >= 65536.0 )
*a -= 65536.0;
if ( ss == 0.0 )
return(0.0);
if ( ss != *(a+1)) {
*(a+2) = sqrt(ss / 2.0);
*(a+1) = ss;
}
return( z * rms / *(a+2));
}
void hf2set(fc, zet, a)
double fc, zet, *a;
{
register double pi = 4.0 * atan(1.0);
register double wcp = tan(pi * fc / srate);
register double wcp2 = wcp * wcp;
register double twzwcp = 2.0 * zet * wcp;
*(a+4) = 1.0 / ( 1.0 + twzwcp + wcp2 );
*(a+5) = 2.0 * ( 1.0 - wcp2) * *(a+4);
*(a+6) = -( 1.0 - twzwcp + wcp2) * *(a+4);
}
double hpf2( y, a )
double y, *a;
{
/* 2nd order high pass filter,
* digital recursion formula parameter assignments:
* *a = y1, *(a+1) = y2, *(a+2) = z1, *(a+3) = z2, *(a+4) = p0,
* *(a+5) = q1, *(a+6) = q2.
*/
register double sig = *(a+4) * ( y-*a-*a+*(a+1))
+ *(a+5) * *(a+2) + *(a+6) * *(a+3);
*(a+1) = *a;
*a = y;
*(a+3) = *(a+2);
*(a+2) = sig;
return(sig);
}
void linset(rise, dur, decay, a)
double rise, dur, decay, *a;
{
*(a+3) = 0.0;
if ( rise == 0.0 ) *(a) = 0.0;
else {
*(a) = (long) (rise * srate + 1.5);
*(a+4) = 1.0 / *(a);
*(a+6) = -*(a+4);
}
if ( decay == 0.0 ) *(a+2) = 0.0;
else {
*(a+2) = (long)(decay * srate + 0.5);
*(a+5) = 1.0 / *(a+2);
*(a+7) = 1.0;
}
*(a+1) = (long)(dur * srate + 0.5);
*(a+2) = *(a+1) - *(a+2);
}
double linens(amp, a)
double amp, *a;
{
*(a+3) += 1.0;
if ( *(a+3) <= *(a)) {
*(a+6) += *(a+4);
return( amp * *(a+6));
}
else if ( *(a+3) <= *(a+2))
return(amp);
else if ( *(a+3) > *(a+2)) {
*(a+7) -= *(a+5);
return(amp * *(a+7));
}
else
return(0.0);
}
double nonlin(amp, x, fno)
double amp, x;
int fno;
{
register double frac;
register k, l;
/* interpolating lookup of transfer function for non-linear distortion
(waveshaping) */
k = x + (int)(*(F[fno])/2.0) + 1;
if ( k > (int)*(F[fno] - 1) )
k = (int)*(F[fno]);
else if ( k < 1 )
k = 1;
l = k + 1;
frac = x - (int)x;
return( amp * ( *(F[fno]+k) + ( *(F[fno]+l) - *(F[fno]+k)) * frac));
}
double oscil(amp, si, fno, phs)
double amp, si, *phs;
int fno;
{
/* truncating digital oscillator, negative samp incs ok */
register double sig = amp * *(F[fno] + ((int)(*phs+1.0)));
*phs += si;
while (*phs < 0.0) {
*phs += *(F[fno]);
}
while (*phs >= *(F[fno])) {
*phs -= *(F[fno]);
}
return( sig );
}
double oscil1(amp, si, fno, phs)
double amp, si, *phs;
int fno;
{
register double sig;
/* truncating function lookup, samples function once,
* holds last value if phs exceeds *(F[fno]) i.e. length of function */
if (*phs >= *(F[fno]))
sig = amp * *(F[fno] + (int)*(F[fno]));
else {
if (*phs <= 0.0 )
sig = amp * *(F[fno] + 1);
else
sig = amp * *(F[fno] + ((int)(*phs+1.0)));
}
*phs += si;
return(sig);
}
double osci1(amp, si, fno, phs)
double amp, si, *phs;
int fno;
{
register double sig, frac;
register k, l;
/* interpolating version of oscil1 */
if (*phs >= *(F[fno]))
sig = amp * *(F[fno] + (int)*(F[fno]));
else {
if (*phs <= 0.0 )
sig = amp * *(F[fno] + 1);
else {
k = *phs + 1.0;
l = k + 1;
frac = *phs - (int)*phs;
sig = amp * ( *(F[fno]+k) + ( *(F[fno]+l) - *(F[fno]+k)) * frac);
}
*phs += si;
}
return(sig);
}
double oscili(amp, si, fno, phs)
double amp, si, *phs;
int fno;
{
/* interpolating digital oscillator, negative samp incs ok */
register double sig, frac;
register k, l;
k = *phs + 1.0;
l = k % (int)(*(F[fno])) + 1;
frac = *phs - (int)*phs;
*phs += (si);
while (*phs < 0.0)
*phs += *(F[fno]);
while (*phs >= *(F[fno]))
*phs -= *(F[fno]);
sig = amp * ( *(F[fno]+k) + ( *(F[fno]+l) - *(F[fno]+k)) * frac);
return(sig);
}
void rsnset(cf, bw, scl, xinit, a )
double cf, bw, scl, xinit, *a;
{
/*
* scl = 1.0 sets gain at 1.0 cf
* scl = 2.0 sets gain at 1.0 on random input
* scl = 0.0 means no scaling
*/
register double twopi = 8.0 * atan(1.0);
register double c;
if ( xinit <= 0.0 ) {
*(a+4) = 0.0;
*(a+3) = 0.0;
}
*(a+2) = exp( -twopi * bw / srate );
c = *(a+2) + 1.0;
*(a+1) = 4.0 * *(a+2) / c * cos(twopi * cf / srate );
if ( scl > 1.0 )
*a = sqrt((1.0 - *(a+2)) / c * (c * c - *(a+1) * *(a+1)));
else if ( scl < 1.0)
*a = 1.0;
else
*a = (1.0 - *(a+2)) * sqrt(1.0 - *(a+1) * *(a+1) / (4.0 * *(a+2)));
}
double reson( x, a )
double x, *a;
{
/* y[i] = a[0] * x[i] + a[1] * y[i-1] - a[2] * y[i-2] */
register double y = *a * x + *(a+1) * *(a+3) - *(a+2) * *(a+4);
*(a+4) = *(a+3);
*(a+3) = y;
return(y);
}
void vrsset( pk, xinit, a )
double pk, xinit, *a;
{
if ( xinit <= 0.0 ) {
*(a+4) = 0.0;
*(a+3) = 0.0;
}
/* *(a+1) and *(a+2) to be set during playing time */
*a = 1.0 / pk;
}
double vreson(xin, cf, bw, fl, fno, a)
double xin, cf, bw, fl, *a;
int fno;
{
register double y;
register double pi = 4.0 * atan(1.0);
register double x = 1.0 - pi * bw / srate;
*(a+2) = x * x;
x = 4.0 * *(a+2) / (1.0 + *(a+2));
y = fl * cf / srate;
*(a+1) = vfmult(x, y, fno);
return( reson(xin, a));
}
void mono(output)
double output;
{
*(out+loc) += output;
}
void output(a, b, c, d)
double a, b, c, d;
{
switch(nchnls) {
case 4: *(out+loc+3) += d;
case 3: *(out+loc+2) += c;
case 2: *(out+loc+1) += b;
case 1: *(out+loc) += a;
}
}
void stereo(output, prop)
double output, prop;
{
*(out+loc) += output * prop;
*(out+loc+1) += output * (1.0 - prop);
}
double ilookup(x, fno)
double x;
int fno;
{
/* interpolating table lookup */
register double frac;
register k;
int l;
k = (int)x;
if ( k < 1 )
return( *(F[fno] + 1) );
else if ( k >= *(F[fno]) )
return( *(F[fno]+(int)*(F[fno])) );
else {
l = k + 1;
frac = x - k;
return(*(F[fno]+k) + ( *(F[fno]+l) - *(F[fno]+k)) * frac);
}
}
double vfmult(amp, sl, fno)
double amp, sl;
int fno;
{
register k = ((int)sl % (int)(*(F[fno]))) + 1;
return( amp * *(F[fno] + k));
}
double cpsoct(oct)
double oct;
{
/* linear octave form to cps, Mid C = octave 8 */
return( pow(2.0, oct) * 1.021975);
}
double cpspch(pch)
double pch;
{
/* 8ve.pc to cps */
register double oct = (int)pch;
return( pow(2.0, oct + 8.333333 * (pch-oct)) * 1.021975);
}
double cycle(cps)
double cps;
{
/* cps to samp inc */
return(cps * 512.0 / srate);
}
double octave(oct)
double oct;
{
/* linear octave form to samp inc */
return( pow(2.0, oct) * 523.2511 / srate);
}
double octcps(cps)
double cps;
{
/* cps to linear octave form */
return( log( cps / 1.021975 ) / 0.69314718);
}
double octpch(pch)
double pch;
{
/* 8ve.pc to linear octave */
register double oct = (int)pch;
return( oct + 8.333333 * (pch - oct));
}
double pchcps(cps)
double cps;
{
/* cps to 8ve.pc */
return(pchoct(octcps(cps)));
}
double pchoct(oct)
double oct;
{
/* linear octave form to 8ve.pc */
register double pch = (int)oct;
return((0.12 * ( oct - pch)) + pch);
}
double period(dur)
double dur;
{
/* duration to samp inc */
return(512.0 / srate / dur);
}
double pitch(pch)
double pch;
{
/* 8ve.pc to samp inc */
register double oct = (int)pch;
return( pow(2.0, oct + 8.333333 * (pch-oct) ) * 523.2511 / srate);
}
double sicps(si)
double si;
{
/* samp inc to cps */
return((si * srate) / 512.0);
}
double random(x) /* !!! there is a Mac ToolBox call, Random */
double *x;
{
long n = *x * 1048576.0;
*x = (double)( ((1061L * n + 221589L) % 1048576L)) / 1048576.0;
return(*x);
}
double drand(amp, a)
double amp, *a;
{
*a = random(a);
return( amp * ( 1.0 - (2.0 * *a)));
}
double randf(oldval, factor, seed)
double oldval, factor, *seed;
{
register double range = 2.0 - ( 2.0 * factor);
register double lowbnd, uprbnd;
lowbnd = oldval - range;
if ( lowbnd < -1.0) lowbnd = -1.0;
uprbnd = oldval + range;
if ( uprbnd > 1.0) uprbnd = 1.0;
return(lowbnd + ((uprbnd-lowbnd) * random(seed)));
}
double randfc(amp, freq, a, curv, cdiff)
double amp, freq, *a, curv[], cdiff[];
{
/* freq in Hz
* *a = seed, (1.0 to init)
* a[1] = oldval (0.0)
* a[2] = diff (0.0)
* a[3] = phs (0.0)
* a[4] = factor (0.0...1.0)
*/
register double t, indx;
register i;
indx = ((127.0 / srate) * *(a+3) * freq );
if ( indx > 127.0) {
*(a+3) = 0.0;
indx = 0;
}
if ( *(a+3) == 0.0 ) {
*(a+1) += *(a+2);
/* *(a+2) = randf( *(a+1), *(a+4), a) - *(a+1);*/
*(a+2) = randf( a[1], a[4], &a[0]) - *(a+1);
}
*(a+3) += 1.0;
i = (int)indx;
t = *(curv+i) + (*(cdiff+i) * ( indx - i));
t = ( amp * ( *(a+1) + ( t * *(a+2))));
return(t);
}
double randfi(amp, freq, a )
double amp, freq, *a;
{
/* freq in Hz
* *a = seed, (1.0 to init)
* a[1] = oldval (0.0)
* a[2] = diff (0.0)
* a[3] = phs (0.0)
* a[4] = factor (0.0...1.0)
*/
register double interp = *(a+3) / (srate / freq);
if ( interp >= 1.0) {
*(a+3) = 0.0;
interp = 0.0;
}
if ( *(a+3) == 0.0 ) {
*(a+1) += *(a+2);
*(a+2) = randf( *(a+1), *(a+4), a ) - *(a+1);
}
*(a+3) += 1.0;
return( amp * ( *(a+1) + ( interp * *(a+2)) ));
}
double randh(amp, si, a)
double amp, si, *a;
{
*(a) += si;
if ( *(a) >= 512.0) {
*(a+1) = random((a+1));
*(a) -= 512.0;
}
return( *(a+1) * amp );
}
double randi(amp, si, a)
double amp, si, *a;
{
*(a) += (si / 512.0);
if ( *(a) > 1.0 ) {
*(a) -= 1.0;
*(a+1) = *(a+2);
*(a+2) = random( (a+2) );
*(a+3) = 2.0 * ( *(a+1) - *(a+2) );
*(a+1) = 1.0 - ( *(a+1) * 2.0 ) - (*(a+3) * *(a) );
}
return( ( *(a+1) + *(a+3) * *(a) ) * amp);
}
double alpass(xin, rvt, a)
double xin, rvt, *a;
{
register l;
register double x = comb(xin, rvt, a);
l = *(a+4);
return( x - *(a+3) * *(a+l) );
}
double balnce(y, x, a)
double y, x, *a;
{
register double q = tone(y * y, (a+3));
if ( q == 0.0 ) q = 0.00000001;
return( y * sqrt( tone(x * x, a)) / q);
}
double comb(xin, rvt, a)
double xin, rvt, *a;
{
register k;
register double sig;
if ( rvt != *(a+2)) {
if ( rvt == 0.0 )
*(a+3) = 0.0;
else
*(a+3) = pow(0.001, *(a+1) / rvt );
*(a+3) = 0.0;
*(a+2) = rvt;
}
if ( *(a+4) >= *(a))
*(a+4) = 5.0;
else
*(a+5) += 1.0;
k = (long)*(a+4);
sig = *(a+k);
*(a+k) = (*(a+k) * *(a+3)) + xin;
return(sig);
}
void coscurv(curv, cdiff)
double curv[];
double cdiff[];
{
register double pi = 4.0 * atan(1.0);
register i;
for ( i = 0; i < 128; i++)
*(curv+i) = (1.0 - cos(pi * (i/127.0))) * 0.5;
for ( i = 0; i < 127; i++)
*(cdiff+i) = *(curv+i+1) - *(curv+i);
*(cdiff+127) = 0.0;
}
double buzz(amp, si, hn, fno, phs )
double amp, si, hn, *phs;
int fno;
{
register j = *phs;
register k = (j+1) % 1024;
double sig;
register double h2n = 2.0 * hn;
register double h2np1 = h2n + 1.0;
register double q = (int)( (*phs - (int)*phs) * h2np1) / h2np1;
double d = *(F[fno] + j + 1);
double e = *(F[fno] + k + 1);
d += (e - d) * q;
if ( d == 0.0 )
sig = amp;
else {
k = (int)(h2np1 * *phs) % 1024;
sig = amp * (*(F[fno] + k + 1) / d - 1.0) / h2n;
}
*phs += si;
while (*phs >= 1024.0) *phs -= 1024.0;
return(sig);
}
void rvbset(xinit, a)
double xinit, *a;
{
register i;
register j;
void cmbset();
double xl[6];
xl[0] = 0.0297;
xl[1] = 0.0371;
xl[2] = 0.0411;
xl[3] = 0.0437;
xl[4] = 0.005;
xl[5] = 0.0017;
j = 0;
for (i = 0; i < 6; i++ ) {
cmbset( xl[i], xinit, a+j );
j += (long)*(a+j);
}
}
double reverb(xin, rvt, a )
double xin, rvt, *a;
{
/* after Schroeder */
/* dimension for "a" is (30 + 1538 * srate / 10000) - 1 */
double x;
register i;
register j;
x = 0.0;
j = 0;
for ( i = 0; i < 4; i++ ) {
x += comb(xin, rvt, a+j );
j += (long)*(a+j);
}
x = alpass(x, 0.096835, a+j) * 0.25;
j += (long)*(a+j);
return( alpass(x, 0.32924, a+j));
}
void rvb2set(rvt, xinit, a, b )
double rvt, xinit, *a, *b;
{
/*
* Reverb unit consists of 6 combs in parallel, followed by 1 alpass filter.
* Combs each have a low pass filter built in.
* b[0] to b[5] = delay times (in seconds) for the comb filters.
* b[6] = delay time (in seconds) for the alpass filter.
*
* b[7] to b[12] = gains for low pass filters in combs.
* b[13] = gain for alpass.
*
* if b[0] = 0.0 fixed data (as below) is used, this was taken from
* Andy Moorer's "About this Reverberation Business" and is for 16.66kHz
* sampling rate.
*
* Gains for filters (g2) are calculated as follows:
* g2 = gain * (1.0 - g1)
* where g1 is the low pass filter gain and "gain" is calculated from approx.
* gain = 1.0 - ( 0.366 / reverb_time )
*
* Dimension of array "a" is given by the sum of
* (delay_time * sampling_rate) + 5.5 for each comb and alpass.
* = 6557 for the fixed data at srate = 166667.
* = 7850 for 20000
*/
double del[7];
double filtg[7];
double gain;
register i;
register j;
int lj;
int n;
if ( *b == 0.0) {
*del = 0.05;
*(del+1) = 0.056;
*(del+2) = 0.061;
*(del+3) = 0.068;
*(del+4) = 0.072;
*(del+5) = 0.078;
*(del+6) = 0.006;
*filtg = 0.172;
*(filtg+1) = 0.179;
*(filtg+2) = 0.187;
*(filtg+3) = 0.194;
*(filtg+4) = 0.198;
*(filtg+5) = 0.205;
*(filtg+6) = 0.7;
}
else {
*del = *b;
*(del+1) = *(b+1);
*(del+2) = *(b+2);
*(del+3) = *(b+3);
*(del+4) = *(b+4);
*(del+5) = *(b+5);
*(del+6) = *(b+6);
*filtg = *(b+7);
*(filtg+1) = *(b+8);
*(filtg+2) = *(b+9);
*(filtg+3) = *(b+10);
*(filtg+4) = *(b+11);
*(filtg+5) = *(b+12);
*(filtg+6) = *(b+13);
}
gain = 1.0 - ( 0.366 / rvt);
/*
* *(a+j) = buffer length
* *(a+j+1) = g2, gain of comb
* *(a+j+2) = g1, gain factor
* *(a+j+3) = previous sample for comb lpf
* *(a+j+4) = ptr
*/
j = 0;
for ( i = 0; i < 6; i++ ) {
*(a+j) = 4.0 + (long)( *(del+i) * srate + 0.5);
*(a+j+1) = gain * ( 1.0 - *(filtg+i));
*(a+j+2) = *(filtg+i);
*(a+j+3) = 0.0;
*(a+j+4) = 4.0;
lj = j + 5;
j += (long) *(a+j);
if ( xinit <= 0.0 ) {
for ( n = lj; n < j; n++)
*(a+n) = 0.0;
}
}
/* alpass */
*(a+j) = 4.0 + (long)( *(del+i) * srate + 0.5);
*(a+j+1) = *(filtg+i);
*(a+j+2) = 0.0;
*(a+j+3) = 0.0;
*(a+j+4) = 4.0;
lj = j + 5;
j += (long) *(a+j);
if ( xinit <= 0.0 ) {
for ( n = lj; n < j; n++)
*(a+n) = 0.0;
}
}
double reverb2(xin, a)
double xin, *a;
{
register double x;
register i;
register j;
j = 0;
x = 0.0;
for ( i = 0; i < 6; i++ ) {
/* *(a+j+2) = comb2(xin, a+j) + (*(a+j+2) * *(a+j+1));
x += *(a+j+2);
*/
x += comb2(xin, a+j);
j += (long) *(a+j);
}
return( alpass2(x, a+j) );
}
double alpass2(xin, a)
double xin, *a;
{
register double x = comb2(xin, a);
int l;
if ( *(a+4) >= *a)
*(a+4) = 5.0;
if ( *(a+4) >= *a-1.0)
;
l = (long)*(a+4);
return( x - *(a+1) * *(a+l) );
}
double comb2(xin, a )
double xin, *a;
{
register k;
register l;
register double sig;
if (*(a+4) < ( *a - 2.0 ) ) {
*(a+4) += 1.0;
l = (long) *(a+4);
k = l + 1;
}
else if ( *(a+4) == (*a - 2.0)) {
*(a+4) += 1.0;
l = (long)*(a+4);
k = 5;
}
else {
*(a+4) = 5.0;
l = 5;
k = 6;
}
sig = *(a+k);
*(a+l) = xin + ( *(a+1) * (*(a+k) + (*(a+2) * *(a+l))));
return(sig);
}
double zdelay(sigin, delay_len, buflen, buf, bufptr)
double sigin, delay_len, *buf, *bufptr;
int buflen;
{
register i;
register k;
register j;
register double delsamp;
double frac;
register double temp;
/* first, get the array index */
k = (int)*bufptr;
if ( k >= buflen) {
k = 0;
}
/* stuff the new sample into the buffer */
*(buf+k) = sigin;
/* get the delayed sample's index, and check it's within range */
delsamp = *bufptr - delay_len;
if ( delsamp < 0.0 ) delsamp += buflen;
if ( delsamp >= buflen ) delsamp -= buflen;
/* ok, inc and check new sample index */
(*bufptr)++;
if ( *bufptr >= buflen )
*bufptr = 0.0;
/* get integer indices, will have to wrap around if i is at end of buffer */
i = (int)delsamp;
if ( i < (buflen-1) )
j = i+1;
else
j = 0;
frac = delsamp - i;
temp = *(buf+i);
temp += ((*(buf+j) - temp) * frac );
return(temp);
}
double sdelay(delay_len, buflen, buf, bufptr)
double delay_len, *buf, *bufptr;
int buflen;
{
register i;
register j;
double frac;
register double delsamp = *bufptr - delay_len;
register double temp;
if ( delsamp < 0.0 ) delsamp += buflen;
if ( delsamp >= buflen ) delsamp -= buflen;
i = (int)delsamp;
if ( i < (buflen-1) )
j = i+1;
else
j = 0;
frac = delsamp - i;
temp = *(buf+i);
temp += ((*(buf+j) - temp) * frac );
return(temp);
}
read_set(fname, buf, buflen, bptr, fildes)
char *fname;
float buf[];
int buflen;
double *bptr;
int *fildes;
{
register i;
long pos, lseek();
int nread, recno;
for (i = 0; i < buflen; i++ )
*(buf+i) = 0.0;
if ((*fildes = open(fname, 0)) != -1) {
recno = (int)(*bptr / buflen);
*bptr -= (double)(recno * buflen);
nread = 0;
pos = lseek(*fildes, (long)(recno*buflen*sizeof(float)), nread);
if ( (nread = read(*fildes, (char *)buf, (unsigned)(buflen * sizeof(float)) )) == -1){
PstringCopy((char *)theMess1, "\pread failed in read_set");
OSError(theMess1, NIL, theErr);
}
}
else {
PstringCopy((char *)theMess1, "\pfailed to open sound file");
OSError(theMess1, NIL, theErr);
}
}
double readsfi(fildes, si, buf, buflen, bptr)
int fildes;
int buflen;
double si, *bptr;
float buf[];
{
/*
* interpolating soundfile read,
* negative and fractional sample increments are accommodated.
*/
register i;
register k;
double frac;
double oldsamp;
long pos, lseek();
int nread;
int new_read;
long reclen = buflen * sizeof(float);
new_read = 0;
/* ensure *bptr points to somewhere within the current record */
if ( *bptr < -reclen ) {
*bptr += si;
return(0.0);
}
while ( *bptr < 0.0 ) {
pos = lseek(fildes, -reclen, 1 );
*bptr += buflen;
new_read = -1;
}
while ( *bptr >= buflen ) {
*bptr -= buflen;
new_read = 1;
if ( *bptr >= buflen )
pos = lseek(fildes, reclen, 1 );
}
if ( new_read == -1) {
pos = lseek(fildes, -reclen, 1 );
if ( pos < 0 ) {
*bptr += si;
for (i = 0; i < buflen; i++ )
*(buf+i) = 0.0;
return(0.0);
}
if ((nread = read(fildes, (char *)buf, (unsigned)reclen)) == -1) {
perror("read failed in readsfi (new_read = -1)");
return(0.0);
}
}
else if ( new_read == 1) {
if ( (nread = read(fildes, (char *)buf, (unsigned)reclen)) == -1 ) {
perror("read failed in readsfi (new_read = 1)");
return(0.0);
}
if ( nread < (int)reclen ) {
for ( i = (int)(nread/sizeof(float)); i < buflen; i++ ) {
*(buf+i) = 0.0;
}
}
}
/* now check for interpolation */
i = (int)*bptr;
frac = *bptr - i;
*bptr += si;
if ( frac == 0.0) {
return( *(buf+i) );
}
k = i + 1;
/* check if sample k is in this record */
oldsamp = *(buf+i);
if ( k >= buflen ) {
/*pos = lseek(fildes, reclen, 1 );*/
*bptr -= buflen;
k = 0;
if ((nread = read(fildes, (char *)buf, (unsigned)reclen)) == -1 ) {
perror("read failed in readsfi near end of routine");
return(0.0);
}
if ( nread < (int)reclen ) {
for ( i = (nread/sizeof(float)); i < buflen; i++ ) {
*(buf+i) = 0.0;
}
}
}
return( oldsamp + ( (*(buf+k) - oldsamp) * frac ) );
}
Boolean SF_FLOAT_ReadSet(buf, buflen, bptr, myPBlkPtr, SampPtr, StartSamp, EndSamp)
double *buf;
int buflen;
double *bptr, *SampPtr;
long *StartSamp, *EndSamp;
ParmBlkPtr myPBlkPtr;
{
/* set file pos and get the buffer full*/
register i;
long nBytes;
float *fptr1, *fptr2;
double *dptr;
long nSamps;
long theLastSamp;
long nrecs;
fptr1 = (float *)NewPtr(buflen * sizeof(float) );
if ( fptr1 == NIL ) {
PstringCopy((char *)theMess1, "\pNot enough memory in MACread_set");
OSError(theMess1, NIL, theErr);
}
for (i = 0, dptr = buf; i < buflen; i++ )
*dptr++ = 0.0;
for (i = 0, fptr2 = fptr1; i < buflen; i++ )
*fptr2++ = 0.0;
/* StartSamp points to the actual sample number */
myPBlkPtr->ioParam.ioPosMode = fsFromStart;
myPBlkPtr->ioParam.ioCompletion = NIL;
/* we round off to a buffer boundary */
myPBlkPtr->ioParam.ioPosOffset = (long)(*StartSamp * sizeof(float));
myPBlkPtr->ioParam.ioBuffer = (Ptr)fptr1;
myPBlkPtr->ioParam.ioReqCount = (long)(buflen*sizeof(float));
*SampPtr = (double)*StartSamp;
*EndSamp = *StartSamp + buflen;
*bptr = 0.0;
theErr = PBRead(myPBlkPtr, FALSE);
if (theErr != noErr ) {
if ( theErr == eofErr ) {
/* round off to a record boundary and read the
remaining portion of the file into the buffer */
myPBlkPtr->ioParam.ioCompletion = NIL;
theErr = PBGetEOF(myPBlkPtr, FALSE);
theLastSamp = (long)myPBlkPtr->ioParam.ioMisc / sizeof(float);
nrecs = (long)theLastSamp / buflen;
*StartSamp = nrecs * buflen;
myPBlkPtr->ioParam.ioPosMode = fsFromStart;
myPBlkPtr->ioParam.ioCompletion = NIL;
myPBlkPtr->ioParam.ioPosOffset = (long)(*StartSamp * sizeof(float));
myPBlkPtr->ioParam.ioReqCount = (theLastSamp - *StartSamp) * sizeof(float);
theErr = PBRead(myPBlkPtr, FALSE);
*EndSamp = theLastSamp;
*bptr = (*EndSamp - *StartSamp) - 1;
*SampPtr = (double)*EndSamp-1;
}
else {
PstringCopy((char *)theMess1, "\pError reading from the soundfile");
OSError(theMess1, NIL, theErr);
}
}
else {
*bptr = 0.0;
*EndSamp = *StartSamp + buflen;
}
nBytes = myPBlkPtr->ioParam.ioActCount;
nSamps = nBytes / sizeof(float);
for ( i = 0, dptr = buf, fptr2 = fptr1; i < nSamps; i++ )
*dptr++ = (double)*fptr1++;
DisposPtr((Ptr)fptr1);
DisposPtr((Ptr)fptr2);
DisposPtr((Ptr)dptr);
return(TRUE);
}
double SF_FLOAT_Read(myPBlkPtr, si, buf, buflen, bptr, SampPtr, StartSamp, EndSamp)
ParmBlkPtr myPBlkPtr;
int buflen;
double si;
double *bptr; /* points to a sample no WITHIN the buffer */
double *buf;
long *StartSamp, *EndSamp;
double *SampPtr;
{
/*
* interpolating soundfile read,
* negative and fractional sample increments are accommodated.
*/
register i;
register k;
register double frac;
register double thisSamp;
float oldSamp, *PtrToOldSamp;
long nBytes;
float *Fptr;
long nSamps;
if ( *SampPtr < (double)*StartSamp ) { /* read previous buffer */
if ( *SampPtr < 0 )
return(0.0);
Fptr = (float *)NewPtr(buflen * sizeof(float) );
/* zero out the buffers */
for (i = 0; i < buflen; i++ ) *(buf+i) = 0.0;
for (i = 0; i < buflen; i++ ) *(Fptr+i) = 0.0;
myPBlkPtr->ioParam.ioBuffer = (Ptr)Fptr;
*EndSamp = *StartSamp;
*StartSamp = *EndSamp - buflen;
*bptr += buflen;
if ( *StartSamp < 0L ) {
*StartSamp = 0L;
myPBlkPtr->ioParam.ioReqCount =
(long) ((*EndSamp - *StartSamp) * sizeof(float));
}
else {
myPBlkPtr->ioParam.ioReqCount = (long)(buflen*sizeof(float));
}
myPBlkPtr->ioParam.ioPosOffset = (long)(*StartSamp*sizeof(float));
theErr = PBRead(myPBlkPtr, FALSE);
if ( theErr != noErr ) {
if ( myPBlkPtr->ioParam.ioPosOffset < NIL || theErr == eofErr || theErr == posErr )
/* mark is outside file bounds (= %ld\n", myPBlkPtr->ioParam.ioPosOffset;*/
;
*SampPtr += si;
*bptr += si;
return(0.0);
}
/* otherwise */
nBytes = myPBlkPtr->ioParam.ioActCount;
nSamps = nBytes / sizeof(float);
for ( i = 0; i < nSamps; i++ )
*(buf+i) = (double)*(Fptr+i);
DisposPtr((Ptr)Fptr);
}
else if ( *SampPtr >= (double)*EndSamp ) { /* read next bufferful */
/* works ok for p[os si gg12/6/90 */
if ( *StartSamp >= *EndSamp ) /* must have already read past EOF */
return(0.0);
Fptr = (float *)NewPtr(buflen * sizeof(float) );
/* zero out the buffers */
for (i = 0; i < buflen; i++ ) *(buf+i) = 0.0;
for (i = 0; i < buflen; i++ ) *(Fptr+i) = 0.0;
myPBlkPtr->ioParam.ioBuffer = (Ptr)Fptr;
*StartSamp = (long)*SampPtr;
*EndSamp = *StartSamp + buflen;
*bptr -= buflen;
myPBlkPtr->ioParam.ioPosOffset = (long)(*SampPtr*sizeof(float));
myPBlkPtr->ioParam.ioReqCount = (long)(buflen*sizeof(float));
theErr = PBRead(myPBlkPtr, FALSE);
if ( theErr != noErr ) {
if ( theErr == eofErr ) {
if (myPBlkPtr->ioParam.ioActCount == 0L ) {
DisposPtr((Ptr)Fptr);
*SampPtr = (double)*EndSamp;
*StartSamp = *EndSamp;
*SampPtr += si;
*bptr += si;
return(0.0);
}
*EndSamp = *StartSamp +
(myPBlkPtr->ioParam.ioActCount / sizeof(float));
}
if ( myPBlkPtr->ioParam.ioPosOffset < NIL || theErr == eofErr || theErr == posErr )
/* mark is outside file bounds (= %ld\n", myPBlkPtr->ioParam.ioPosOffset;*/
;
DisposPtr((Ptr)Fptr);
}
/* otherwise */
nBytes = myPBlkPtr->ioParam.ioActCount;
nSamps = nBytes / sizeof(float);
for ( i = 0; i < nSamps; i++ )
*(buf+i) = (double)*(Fptr+i);
DisposPtr((Ptr)Fptr);
}
/* now check for interpolation */
i = (int)*bptr;
frac = *bptr - i;
*SampPtr += si;
*bptr += si;
if ( frac == 0.0) {
return(*(buf+i) );
}
k = i + 1;
/* check if sample k is in this record */
thisSamp = *(buf+i);
if ( k >= buflen ) {
if ( si < 0.0 ) {
/* we must have a negative, fractional sample increment, we have probably
just read a new record and must now interpolate between th last sample in
this rec and the first sample in the one we just discarded. To save hassle,
just read that sample in, do the interpolation and forget it! */
PtrToOldSamp = &oldSamp;
myPBlkPtr->ioParam.ioBuffer = (Ptr)PtrToOldSamp;
myPBlkPtr->ioParam.ioPosOffset = (long)((*SampPtr+1.0)*sizeof(float));
myPBlkPtr->ioParam.ioReqCount = (long)sizeof(float);
theErr = PBRead(myPBlkPtr, FALSE);
if ( theErr == noErr ) {
return( (double)(thisSamp + ( (oldSamp - thisSamp) * frac ) ));
}
/* problem reading the sample, just return the the current sample */
return(thisSamp);
}
k = 0;
Fptr = (float *)NewPtr(buflen * sizeof(float) );
for (i = 0; i < buflen; i++ ) *(buf+i) = 0.0;
for (i = 0; i < buflen; i++ ) *(Fptr+i) = 0.0;
myPBlkPtr->ioParam.ioBuffer = (Ptr)Fptr;
*StartSamp = (long)*SampPtr;
*EndSamp = *StartSamp + buflen;
myPBlkPtr->ioParam.ioPosOffset = (long)(*SampPtr*sizeof(float));
myPBlkPtr->ioParam.ioReqCount = (long)(buflen*sizeof(float));
theErr = PBRead(myPBlkPtr, FALSE);
if ( theErr != noErr ) {
if ( theErr == eofErr ) {
if (myPBlkPtr->ioParam.ioActCount == 0L ) {
DisposPtr((Ptr)Fptr);
*SampPtr = (double)*EndSamp;
*StartSamp = *EndSamp;
*SampPtr += si;
*bptr += si;
return(0.0);
}
*EndSamp = *StartSamp +
(myPBlkPtr->ioParam.ioActCount / sizeof(float));
}
else {
DisposPtr((Ptr)Fptr);
return(0.0);
}
if ( myPBlkPtr->ioParam.ioPosOffset < NIL || theErr == eofErr || theErr == posErr )
;
DisposPtr((Ptr)Fptr);
return(0.0);
}
nBytes = myPBlkPtr->ioParam.ioActCount;
nSamps = nBytes / sizeof(float);
for ( i = 0; i < nSamps; i++ )
*(buf+i) = (double)*(Fptr+i);
DisposPtr((Ptr)Fptr);
*bptr -= buflen;
}
return( (double)(thisSamp + ( (*(buf+k) - thisSamp) * frac ) ));
}
/*-------------------------------------------------------------------------------*/
Boolean SF_SD_1_ReadSet(buf, buflen, bptr, myPBlkPtr, SampPtr, StartSamp, EndSamp)
double *buf;
int buflen;
double *bptr, *SampPtr;
long *StartSamp, *EndSamp;
ParmBlkPtr myPBlkPtr;
{
/* set file pos and get the buffer full*/
register i;
long nBytes;
int *iptr1, *iptr2;
double *dptr;
long nSamps;
long theLastSamp;
long nrecs;
WaveRec Header;
WavPtr HeaderPtr;
/* first, read the header info */
HeaderPtr = &Header;
nBytes = SD_HEADER_SIZE;
myPBlkPtr->ioParam.ioPosMode = fsFromStart;
myPBlkPtr->ioParam.ioPosOffset = 0L;
myPBlkPtr->ioParam.ioBuffer = (Ptr)HeaderPtr;
myPBlkPtr->ioParam.ioReqCount = nBytes;
theErr = PBRead(&myPBlkPtr->ioParam, FALSE);
if (theErr != noErr ) {
PstringCopy((char *)theMess1, "\pError reading SD file Header");
OSError(theMess1, NIL, theErr);
}
nSamps = Header.FileSize / sizeof(int);
iptr1 = (int *)NewPtr(buflen * sizeof(int) );
if ( iptr1 == NIL ) {
PstringCopy((char *)theMess1, "\pNot enough memory in SF_SD_ReadSet");
OSError(theMess1, NIL, theErr);
}
for (i = 0, dptr = buf, iptr2 = iptr1; i < buflen; i++ ) {
*dptr++ = 0.0;
*iptr2++ = 0;
}
/* StartSamp points to the actual sample number, we add on header offset */
*StartSamp += (SD_HEADER_SIZE / sizeof(int));
myPBlkPtr->ioParam.ioPosMode = fsFromStart;
myPBlkPtr->ioParam.ioCompletion = NIL;
/* we round off to a buffer boundary */
myPBlkPtr->ioParam.ioPosOffset = (long)(*StartSamp * sizeof(int));
myPBlkPtr->ioParam.ioBuffer = (Ptr)iptr1;
myPBlkPtr->ioParam.ioReqCount = (long)(buflen*sizeof(int));
*SampPtr = (double)*StartSamp;
*EndSamp = *StartSamp + buflen;
*bptr = 0.0;
theErr = PBRead(myPBlkPtr, FALSE);
if (theErr != noErr ) {
if ( theErr == eofErr ) {
/* round off to a record boundary and read the
remaining portion of the file into the buffer */
myPBlkPtr->ioParam.ioCompletion = NIL;
theErr = PBGetEOF(myPBlkPtr, FALSE);
theLastSamp = (long)myPBlkPtr->ioParam.ioMisc / sizeof(int);
theLastSamp -= (SD_HEADER_SIZE / sizeof(int));
nrecs = (long)theLastSamp / buflen;
*StartSamp = (nrecs * buflen) + (SD_HEADER_SIZE / sizeof(int));
myPBlkPtr->ioParam.ioPosMode = fsFromStart;
myPBlkPtr->ioParam.ioCompletion = NIL;
myPBlkPtr->ioParam.ioPosOffset = (long)(*StartSamp * sizeof(int));
myPBlkPtr->ioParam.ioReqCount = (theLastSamp - *StartSamp) * sizeof(int);
theErr = PBRead(myPBlkPtr, FALSE);
*EndSamp = theLastSamp;
*bptr = (*EndSamp - *StartSamp) - 1;
*SampPtr = (double)*EndSamp-1;
}
else {
PstringCopy((char *)theMess1, "\pError reading from the soundfile");
OSError(theMess1, NIL, theErr);
}
}
else {
*bptr = 0.0;
*EndSamp = *StartSamp + buflen;
}
nBytes = myPBlkPtr->ioParam.ioActCount;
nSamps = nBytes / sizeof(int);
for ( i = 0, dptr = buf, iptr2 = iptr1; i < nSamps; i++ )
*dptr++ = (double)*iptr1++;
DisposPtr((Ptr)iptr1);
DisposPtr((Ptr)iptr2);
DisposPtr((Ptr)dptr);
return(TRUE);
}
double SF_SD_1_Read(myPBlkPtr, si, buf, buflen, bptr, SampPtr, StartSamp, EndSamp)
ParmBlkPtr myPBlkPtr;
int buflen;
double si;
double *bptr; /* points to a sample no WITHIN the buffer */
double *buf;
long *StartSamp, *EndSamp;
double *SampPtr;
{
/*
* interpolating soundfile read of Digidesign's Sound Designer¬ format files
* negative and fractional sample increments are accommodated.
*/
register i;
register k;
register double frac;
register int thisSamp;
int oldSamp, *PtrToOldSamp;
long nBytes;
int *Iptr;
long nSamps;
if ( *SampPtr < (double)*StartSamp ) { /* read previous buffer */
if ( *SampPtr < (SD_HEADER_SIZE / sizeof(int)) )
return(0.0);
Iptr = (int *)NewPtr(buflen * sizeof(int) );
/* zero out the buffers */
for (i = 0; i < buflen; i++ ) *(buf+i) = 0.0;
for (i = 0; i < buflen; i++ ) *(Iptr+i) = 0.0;
myPBlkPtr->ioParam.ioBuffer = (Ptr)Iptr;
*EndSamp = *StartSamp;
*StartSamp = *EndSamp - buflen;
*bptr += buflen;
if ( *StartSamp < (SD_HEADER_SIZE / sizeof(int)) ) {
*StartSamp = SD_HEADER_SIZE / sizeof(int);
myPBlkPtr->ioParam.ioReqCount =
(long) ((*EndSamp - *StartSamp) * sizeof(int));
}
else {
myPBlkPtr->ioParam.ioReqCount = (long)(buflen*sizeof(int));
}
myPBlkPtr->ioParam.ioPosOffset = (long)(*StartSamp*sizeof(int));
theErr = PBRead(myPBlkPtr, FALSE);
if ( theErr != noErr ) {
if ( myPBlkPtr->ioParam.ioPosOffset < NIL || theErr == eofErr || theErr == posErr )
/* mark is outside file bounds (= %ld\n", myPBlkPtr->ioParam.ioPosOffset;*/
;
*SampPtr += si;
*bptr += si;
return(0.0);
}
/* otherwise */
nBytes = myPBlkPtr->ioParam.ioActCount;
nSamps = nBytes / sizeof(int);
for ( i = 0; i < nSamps; i++ )
*(buf+i) = (double)*(Iptr+i);
DisposPtr((Ptr)Iptr);
}
else if ( *SampPtr >= (double)*EndSamp ) { /* read next bufferful */
if ( *StartSamp >= *EndSamp ) /* must have already read past EOF */
return(0.0);
Iptr = (int *)NewPtr(buflen * sizeof(int) );
/* zero out the buffers */
for (i = 0; i < buflen; i++ ) *(buf+i) = 0.0;
for (i = 0; i < buflen; i++ ) *(Iptr+i) = 0.0;
myPBlkPtr->ioParam.ioBuffer = (Ptr)Iptr;
*StartSamp = (long)*SampPtr;
*EndSamp = *StartSamp + buflen;
*bptr -= buflen;
myPBlkPtr->ioParam.ioPosOffset = (long)(*SampPtr*sizeof(int));
myPBlkPtr->ioParam.ioReqCount = (long)(buflen*sizeof(int));
theErr = PBRead(myPBlkPtr, FALSE);
if ( theErr != noErr ) {
if ( theErr == eofErr ) {
if (myPBlkPtr->ioParam.ioActCount == 0L ) {
DisposPtr((Ptr)Iptr);
*SampPtr = (double)*EndSamp;
*StartSamp = *EndSamp;
*SampPtr += si;
*bptr += si;
return(0.0);
}
*EndSamp = *StartSamp +
(myPBlkPtr->ioParam.ioActCount / sizeof(int));
}
if ( myPBlkPtr->ioParam.ioPosOffset < NIL || theErr == eofErr || theErr == posErr )
/* mark is outside file bounds (= %ld\n", myPBlkPtr->ioParam.ioPosOffset;*/
;
DisposPtr((Ptr)Iptr);
}
/* otherwise */
nBytes = myPBlkPtr->ioParam.ioActCount;
nSamps = nBytes / sizeof(int);
for ( i = 0; i < nSamps; i++ )
*(buf+i) = (double)*(Iptr+i);
DisposPtr((Ptr)Iptr);
}
/* now check for interpolation */
i = (int)*bptr;
frac = *bptr - i;
*SampPtr += si;
*bptr += si;
if ( frac == 0.0) {
return(*(buf+i) );
}
k = i + 1;
/* check if sample k is in this record */
thisSamp = *(buf+i);
if ( k >= buflen ) {
if ( si < 0.0 ) {
/* we must have a negative, fractional sample increment, we have probably
just read a new record and must now interpolate between th last sample in
this rec and the first sample in the one we just discarded. To save hassle,
just read that sample in, do the interpolation and forget it! */
PtrToOldSamp = &oldSamp;
myPBlkPtr->ioParam.ioBuffer = (Ptr)PtrToOldSamp;
myPBlkPtr->ioParam.ioPosOffset = (long)((*SampPtr+1.0)*sizeof(int));
myPBlkPtr->ioParam.ioReqCount = (long)sizeof(int);
theErr = PBRead(myPBlkPtr, FALSE);
if ( theErr == noErr ) {
return( (double)(thisSamp + ( (oldSamp - thisSamp) * frac ) ));
}
/* problem reading the sample, just return the the current sample */
return(thisSamp);
}
k = 0;
Iptr = (int *)NewPtr(buflen * sizeof(int) );
for (i = 0; i < buflen; i++ ) *(buf+i) = 0.0;
for (i = 0; i < buflen; i++ ) *(Iptr+i) = 0.0;
myPBlkPtr->ioParam.ioBuffer = (Ptr)Iptr;
*StartSamp = (long)*SampPtr;
*EndSamp = *StartSamp + buflen;
myPBlkPtr->ioParam.ioPosOffset = (long)(*SampPtr*sizeof(int));
myPBlkPtr->ioParam.ioReqCount = (long)(buflen*sizeof(int));
theErr = PBRead(myPBlkPtr, FALSE);
if ( theErr != noErr ) {
if ( theErr == eofErr ) {
if (myPBlkPtr->ioParam.ioActCount == 0L ) {
DisposPtr((Ptr)Iptr);
*SampPtr = (double)*EndSamp;
*StartSamp = *EndSamp;
*SampPtr += si;
*bptr += si;
return(0.0);
}
*EndSamp = *StartSamp +
(myPBlkPtr->ioParam.ioActCount / sizeof(int));
}
else {
DisposPtr((Ptr)Iptr);
return(0.0);
}
if ( myPBlkPtr->ioParam.ioPosOffset < NIL || theErr == eofErr || theErr == posErr )
;
DisposPtr((Ptr)Iptr);
return(0.0);
}
nBytes = myPBlkPtr->ioParam.ioActCount;
nSamps = nBytes / sizeof(int);
for ( i = 0; i < nSamps; i++ )
*(buf+i) = (double)*(Iptr+i);
DisposPtr((Ptr)Iptr);
*bptr -= buflen;
}
return( (double)(thisSamp + ( (*(buf+k) - thisSamp) * frac ) ));
}
/*****************************************************************/
Boolean SF_SD_2_ReadSet(buf, buflen, bptr, myPBlkPtr, SampPtr, StartSamp, EndSamp)
double *buf;
int buflen;
double *bptr, *SampPtr;
long *StartSamp, *EndSamp;
ParmBlkPtr myPBlkPtr;
{
/* set file pos and get the buffer full*/
register i;
long nBytes;
int *iptr1, *iptr2;
double *dptr;
long nSamps;
long theLastSamp;
long nrecs;
WaveRec Header;
WavPtr HeaderPtr;
iptr1 = (int *)NewPtr(buflen * sizeof(int) );
if ( iptr1 == NIL ) {
PstringCopy((char *)theMess1, "\pNot enough memory in SF_SD_ReadSet");
OSError(theMess1, NIL, theErr);
}
for (i = 0, dptr = buf, iptr2 = iptr1; i < buflen; i++ ) {
*dptr++ = 0.0;
*iptr2++ = 0;
}
/* StartSamp points to the actual sample number */
myPBlkPtr->ioParam.ioPosMode = fsFromStart;
myPBlkPtr->ioParam.ioCompletion = NIL;
/* we round off to a buffer boundary */
myPBlkPtr->ioParam.ioPosOffset = (long)(*StartSamp * sizeof(int));
myPBlkPtr->ioParam.ioBuffer = (Ptr)iptr1;
myPBlkPtr->ioParam.ioReqCount = (long)(buflen*sizeof(int));
*SampPtr = (double)*StartSamp;
*EndSamp = *StartSamp + buflen;
*bptr = 0.0;
theErr = PBRead(myPBlkPtr, FALSE);
if (theErr != noErr ) {
if ( theErr == eofErr ) {
/* round off to a record boundary and read the
remaining portion of the file into the buffer */
myPBlkPtr->ioParam.ioCompletion = NIL;
theErr = PBGetEOF(myPBlkPtr, FALSE);
theLastSamp = (long)myPBlkPtr->ioParam.ioMisc / sizeof(int);
nrecs = (long)theLastSamp / buflen;
*StartSamp = nrecs * buflen;
myPBlkPtr->ioParam.ioPosMode = fsFromStart;
myPBlkPtr->ioParam.ioCompletion = NIL;
myPBlkPtr->ioParam.ioPosOffset = (long)(*StartSamp * sizeof(int));
myPBlkPtr->ioParam.ioReqCount = (theLastSamp - *StartSamp) * sizeof(int);
theErr = PBRead(myPBlkPtr, FALSE);
*EndSamp = theLastSamp;
*bptr = (*EndSamp - *StartSamp) - 1;
*SampPtr = (double)*EndSamp-1;
}
else {
PstringCopy((char *)theMess1, "\pError reading from the soundfile");
OSError(theMess1, NIL, theErr);
}
}
else {
*bptr = 0.0;
*EndSamp = *StartSamp + buflen;
}
nBytes = myPBlkPtr->ioParam.ioActCount;
nSamps = nBytes / sizeof(int);
for ( i = 0, dptr = buf, iptr2 = iptr1; i < nSamps; i++ )
*dptr++ = (double)*iptr1++;
DisposPtr((Ptr)iptr1);
DisposPtr((Ptr)iptr2);
DisposPtr((Ptr)dptr);
return(TRUE);
}
double SF_SD_2_Read(myPBlkPtr, si, buf, buflen, bptr, SampPtr, StartSamp, EndSamp)
ParmBlkPtr myPBlkPtr;
int buflen;
double si;
double *bptr; /* points to a sample no WITHIN the buffer */
double *buf;
long *StartSamp, *EndSamp;
double *SampPtr;
{
/*
* interpolating soundfile read of Digidesign's Sound Designer II¬ format files
* negative and fractional sample increments are accommodated.
*/
register i;
register k;
register double frac;
register int thisSamp;
int oldSamp, *PtrToOldSamp;
long nBytes;
int *Iptr;
long nSamps;
if ( *SampPtr < (double)*StartSamp ) { /* read previous buffer */
if ( *SampPtr < 0L )
return(0.0);
Iptr = (int *)NewPtr(buflen * sizeof(int) );
/* zero out the buffers */
for (i = 0; i < buflen; i++ ) *(buf+i) = 0.0;
for (i = 0; i < buflen; i++ ) *(Iptr+i) = 0.0;
myPBlkPtr->ioParam.ioBuffer = (Ptr)Iptr;
*EndSamp = *StartSamp;
*StartSamp = *EndSamp - buflen;
*bptr += buflen;
if ( *StartSamp < 0L ) {
*StartSamp = 0L;
myPBlkPtr->ioParam.ioReqCount =
(long) ((*EndSamp - *StartSamp) * sizeof(int));
}
else {
myPBlkPtr->ioParam.ioReqCount = (long)(buflen*sizeof(int));
}
myPBlkPtr->ioParam.ioPosOffset = (long)(*StartSamp*sizeof(int));
theErr = PBRead(myPBlkPtr, FALSE);
if ( theErr != noErr ) {
if ( myPBlkPtr->ioParam.ioPosOffset < NIL || theErr == eofErr || theErr == posErr )
/* mark is outside file bounds (= %ld\n", myPBlkPtr->ioParam.ioPosOffset;*/
;
*SampPtr += si;
*bptr += si;
return(0.0);
}
/* otherwise */
nBytes = myPBlkPtr->ioParam.ioActCount;
nSamps = nBytes / sizeof(int);
for ( i = 0; i < nSamps; i++ )
*(buf+i) = (double)*(Iptr+i);
DisposPtr((Ptr)Iptr);
}
else if ( *SampPtr >= (double)*EndSamp ) { /* read next bufferful */
if ( *StartSamp >= *EndSamp ) /* must have already read past EOF */
return(0.0);
Iptr = (int *)NewPtr(buflen * sizeof(int) );
/* zero out the buffers */
for (i = 0; i < buflen; i++ ) *(buf+i) = 0.0;
for (i = 0; i < buflen; i++ ) *(Iptr+i) = 0.0;
myPBlkPtr->ioParam.ioBuffer = (Ptr)Iptr;
*StartSamp = (long)*SampPtr;
*EndSamp = *StartSamp + buflen;
*bptr -= buflen;
myPBlkPtr->ioParam.ioPosOffset = (long)(*SampPtr*sizeof(int));
myPBlkPtr->ioParam.ioReqCount = (long)(buflen*sizeof(int));
theErr = PBRead(myPBlkPtr, FALSE);
if ( theErr != noErr ) {
if ( theErr == eofErr ) {
if (myPBlkPtr->ioParam.ioActCount == 0L ) {
DisposPtr((Ptr)Iptr);
*SampPtr = (double)*EndSamp;
*StartSamp = *EndSamp;
*SampPtr += si;
*bptr += si;
return(0.0);
}
*EndSamp = *StartSamp +
(myPBlkPtr->ioParam.ioActCount / sizeof(int));
}
if ( myPBlkPtr->ioParam.ioPosOffset < NIL || theErr == eofErr || theErr == posErr )
/* mark is outside file bounds (= %ld\n", myPBlkPtr->ioParam.ioPosOffset;*/
;
DisposPtr((Ptr)Iptr);
}
/* otherwise */
nBytes = myPBlkPtr->ioParam.ioActCount;
nSamps = nBytes / sizeof(int);
for ( i = 0; i < nSamps; i++ )
*(buf+i) = (double)*(Iptr+i);
DisposPtr((Ptr)Iptr);
}
/* now check for interpolation */
i = (int)*bptr;
frac = *bptr - i;
*SampPtr += si;
*bptr += si;
if ( frac == 0.0) {
return(*(buf+i) );
}
k = i + 1;
/* check if sample k is in this record */
thisSamp = *(buf+i);
if ( k >= buflen ) {
if ( si < 0.0 ) {
/* we must have a negative, fractional sample increment, we have probably
just read a new record and must now interpolate between th last sample in
this rec and the first sample in the one we just discarded. To save hassle,
just read that sample in, do the interpolation and forget it! */
PtrToOldSamp = &oldSamp;
myPBlkPtr->ioParam.ioBuffer = (Ptr)PtrToOldSamp;
myPBlkPtr->ioParam.ioPosOffset = (long)((*SampPtr+1.0)*sizeof(int));
myPBlkPtr->ioParam.ioReqCount = (long)sizeof(int);
theErr = PBRead(myPBlkPtr, FALSE);
if ( theErr == noErr ) {
return( (double)(thisSamp + ( (oldSamp - thisSamp) * frac ) ));
}
/* problem reading the sample, just return the the current sample */
return(thisSamp);
}
k = 0;
Iptr = (int *)NewPtr(buflen * sizeof(int) );
for (i = 0; i < buflen; i++ ) *(buf+i) = 0.0;
for (i = 0; i < buflen; i++ ) *(Iptr+i) = 0.0;
myPBlkPtr->ioParam.ioBuffer = (Ptr)Iptr;
*StartSamp = (long)*SampPtr;
*EndSamp = *StartSamp + buflen;
myPBlkPtr->ioParam.ioPosOffset = (long)(*SampPtr*sizeof(int));
myPBlkPtr->ioParam.ioReqCount = (long)(buflen*sizeof(int));
theErr = PBRead(myPBlkPtr, FALSE);
if ( theErr != noErr ) {
if ( theErr == eofErr ) {
if (myPBlkPtr->ioParam.ioActCount == 0L ) {
DisposPtr((Ptr)Iptr);
*SampPtr = (double)*EndSamp;
*StartSamp = *EndSamp;
*SampPtr += si;
*bptr += si;
return(0.0);
}
*EndSamp = *StartSamp +
(myPBlkPtr->ioParam.ioActCount / sizeof(int));
}
else {
DisposPtr((Ptr)Iptr);
return(0.0);
}
if ( myPBlkPtr->ioParam.ioPosOffset < NIL || theErr == eofErr || theErr == posErr )
;
DisposPtr((Ptr)Iptr);
return(0.0);
}
nBytes = myPBlkPtr->ioParam.ioActCount;
nSamps = nBytes / sizeof(int);
for ( i = 0; i < nSamps; i++ )
*(buf+i) = (double)*(Iptr+i);
DisposPtr((Ptr)Iptr);
*bptr -= buflen;
}
return( (double)(thisSamp + ( (*(buf+k) - thisSamp) * frac ) ));
}